package StudyCode.summary.zipfile;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.*;
import java.security.Key;
import java.security.SecureRandom;
import java.util.Enumeration;
import java.util.UUID;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

/**
 * 版权所有 科技与人文(www.tah1986.com)
 */
public class DecryptUnzip {
	public static void decryptUnzip(String srcFile, String target,
	                                String keyFile) throws Exception {
		File temp = new File(UUID.randomUUID().toString() + ".zip");
		temp.deleteOnExit();
		decrypt(srcFile, temp.getAbsolutePath(), getKey(keyFile));
		unzip(temp.getAbsolutePath(), target);
		temp.delete();
	}

	public static void decrypt(String srcFile, String destFile,
	                           Key privateKey) throws Exception {
		SecureRandom sr = new SecureRandom();
		Cipher ciphers = Cipher.getInstance("AES/CBC/PKCS5Padding");
		IvParameterSpec spec = new IvParameterSpec(privateKey.getEncoded());
		ciphers.init(Cipher.DECRYPT_MODE, privateKey, spec, sr);
		FileInputStream fis = new FileInputStream(srcFile);
		FileOutputStream fos = new FileOutputStream(destFile);
		byte[] b = new byte[2064];
		int byteread = 0;
		while ((byteread = fis.read(b)) != -1) {
			fos.write(ciphers.doFinal(b, 0, byteread));
		}
		fos.close();
		fis.close();
	}

	public static Key getKey(String keyPath) throws Exception {
		FileInputStream fis = new FileInputStream(keyPath);
		byte[] b = new byte[16];
		fis.read(b);
		SecretKeySpec dks = new SecretKeySpec(b, "AES");
		fis.close();
		return dks;
	}

	public static void unzip(String zipFileName, String target)
			throws Exception {
		ZipFile zipfile = new ZipFile(zipFileName);
		Enumeration subFiles = zipfile.entries();
		ZipEntry zipEntry = null;
		byte[] buf = new byte[1024];
		while (subFiles.hasMoreElements()) {
			zipEntry = (ZipEntry) subFiles.nextElement();
			if (zipEntry.isDirectory()) {
				continue;
			}
			OutputStream os = new BufferedOutputStream(
					new FileOutputStream(getRealFileName(target,
							zipEntry.getName())));
			InputStream is = new BufferedInputStream(
					zipfile.getInputStream(zipEntry));
			int readLen = 0;
			while ((readLen = is.read(buf, 0, 1024)) != -1) {
				os.write(buf, 0, readLen);
			}
			is.close();
			os.close();
		}
		zipfile.close();
	}

	private static File getRealFileName(String source, String absFileName) {
		String[] dirs = absFileName.split("/");
		File file = new File(source);
		if (dirs.length > 1) {
			for (int i = 0; i < dirs.length - 1; i++) {
				file = new File(file, dirs[i]);
			}
		}
		if (!file.exists()) {
			file.mkdirs();
		}
		file = new File(file, dirs[dirs.length - 1]);
		return file;
	}
}
